package org.esk.dablog.gwt.dablog.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.*;
import org.esk.dablog.gwt.dablog.client.model.ClientForumTopicEntry;
import org.esk.dablog.gwt.dablog.client.model.ClientForumPostEntry;
import org.esk.dablog.gwt.dablog.client.model.ClientForumComment;

import java.util.List;
import java.util.Iterator;
import java.util.Map;
import java.util.HashMap;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class Forum implements EntryPoint {
    private EntryGWTServiceAsync entryService = EntryGWTService.App.getInstance();

    /**
     * This is the entry point method.
     */
    public void onModuleLoad() {
        entryService.listForumTopics(new AsyncCallback() {
            public void onFailure(Throwable caught) {
                Window.alert("RPC failed: " + caught.getMessage());
            }

            public void onSuccess(Object result) {
                List topics = (List) result;
                for (Iterator r = topics.iterator(); r.hasNext();) {
                    ClientForumTopicEntry topic = (ClientForumTopicEntry) r.next();
                    updateTopic(topic);
                }
            }
        });

    }

    /**
     * updates topic entry
     * @param topic
     */
    private void updateTopic(final ClientForumTopicEntry topic) {
        Label header = new Label(topic.getHeader());
        final Panel tree = new VerticalPanel();
        tree.setWidth("100%");
//        tree.addTreeListener(new TreeListener() {
//
//            public void onTreeItemSelected(TreeItem item) {
//                handleItemSelection(item);
//            }
//
//            public void onTreeItemStateChanged(TreeItem item) {
//                updateItemState(item);
//            }
//        });

        header.addClickListener(new ClickListener() {
            private boolean isOpened = false;

            public void onClick(Widget sender) {
                if (!isOpened) {
                    updatePosts(tree, topic.getId());
                } else {
                    tree.setVisible(false);
                }
                isOpened = !isOpened;
            }
        });
        RootPanel.get("topic_tree_" + topic.getId()).add(tree);
        RootPanel.get("topic_" + topic.getId()).add(header);
    }

    private Map stateHandlers = new HashMap() {
        {
            put(GWT.getTypeName(new ClientForumPostEntry()),
                    new ForumPostEntryHandler(entryService));
        }
    };

    private Map selectHandlers = new HashMap() {
        {
            put(GWT.getTypeName(new ClientForumComment()),
                    new ForumCommentSelectionHandler());
        }
    };

    /**
     * handles "select/deselect" action
     */
    private void handleItemSelection(TreeItem item) {
        TreeItemHandler handler = (TreeItemHandler) selectHandlers.get(GWT.getTypeName(item.getUserObject()));
        if (handler != null) {
            handler.handle(item);
        }
    }

    /**
     * handles "expand/collapse" action for different types of items
     * @param item
     */
    private void updateItemState(TreeItem item) {
        TreeItemHandler handler = (TreeItemHandler) stateHandlers.get(GWT.getTypeName(item.getUserObject()));
        if (handler != null) {
            handler.handle(item);
        }
    }

    /**
     * updates posts
     * @param id
     */
    private void updatePosts(final Panel tree, long id) {
        for(Iterator r = tree.iterator();r.hasNext();) {
            r.next();
            r.remove();
        }
        tree.setVisible(true);

        entryService.listForumPosts(id, new AsyncCallback() {

            public void onFailure(Throwable caught) {
                Window.alert(caught.getMessage());
            }

            public void onSuccess(Object result) {
                List posts = (List) result;
                for (Iterator r = posts.iterator(); r.hasNext();) {
                    ClientForumPostEntry post = (ClientForumPostEntry) r.next();
                    ForumEntryWidget entry = new ForumEntryWidget(post);
                    tree.add(entry);
                }
            }
        });
    }

    /**
     * Initializes "Post" item with "add comment" link
     * @param item
     */
    private void initItem(TreeItem item) {
        item.addItem("comment on this");
    }

}

